#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
优化的分页管理器
支持真正的数据库分页，避免一次性加载所有数据
集成样本数据服务，支持POST接口方式获取分页数据
"""

import logging
from typing import List, Dict, Any, Optional, Tuple, Callable
from dataclasses import dataclass
from enum import Enum

logger = logging.getLogger(__name__)

class SortOrder(Enum):
    """排序方式"""
    ASC = "ASC"
    DESC = "DESC"

@dataclass
class PaginationInfo:
    """分页信息"""
    current_page: int = 1
    page_size: int = 20
    total_items: int = 0
    total_pages: int = 0
    has_previous: bool = False
    has_next: bool = False
    start_index: int = 0
    end_index: int = 0
    loading: bool = False

class OptimizedPaginationManager:
    """优化的分页管理器"""
    
    def __init__(self, page_size: int = 20, 
                 data_loader: Callable = None,
                 sort_field: str = "updated_at",
                 sort_order: SortOrder = SortOrder.DESC):
        """
        初始化分页管理器
        
        Args:
            page_size: 每页大小
            data_loader: 数据加载函数，用于从数据库获取分页数据
            sort_field: 默认排序字段
            sort_order: 默认排序方式
        """
        self.page_size = page_size
        self.current_page = 1
        self.total_items = 0
        self.total_pages = 0
        self.sort_field = sort_field
        self.sort_order = sort_order
        self.filters = {}
        
        # 数据加载器
        self.data_loader = data_loader
        
        # 当前页数据缓存
        self._current_data = []
        self._loading = False
        
        # 分页信息
        self._pagination_info = PaginationInfo()
        
        # 样本数据服务（可选）
        self.sample_data_service = None
        
        logger.info(f"分页管理器初始化完成: 每页{page_size}条，排序字段{sort_field}，排序方式{sort_order.value}")
    
    def set_data_loader(self, data_loader: Callable):
        """设置数据加载器"""
        self.data_loader = data_loader
        logger.info("数据加载器已设置")
    
    def set_sample_data_service(self, sample_data_service):
        """设置样本数据服务"""
        self.sample_data_service = sample_data_service
        logger.info("样本数据服务已设置")
    
    def set_filters(self, filters: Dict[str, Any]):
        """设置过滤条件"""
        self.filters = filters
        self.current_page = 1  # 重置到第一页
        logger.info(f"过滤条件已设置: {filters}")
    
    def set_sorting(self, sort_field: str, sort_order: SortOrder):
        """设置排序方式"""
        if self.sort_field != sort_field or self.sort_order != sort_order:
            self.sort_field = sort_field
            self.sort_order = sort_order
            self.current_page = 1  # 重置到第一页
            logger.info(f"排序方式已设置: 字段{sort_field}，方式{sort_order.value}")
    
    def set_page_size(self, page_size: int):
        """设置每页大小"""
        if page_size > 0 and page_size != self.page_size:
            self.page_size = page_size
            self.current_page = 1  # 重置到第一页
            logger.info(f"每页大小已设置: {page_size}条")
    
    def _load_current_page(self):
        """加载当前页数据"""
        if self._loading:
            logger.debug("数据正在加载中，跳过重复请求")
            return
        
        try:
            self._loading = True
            self._update_pagination_info(loading=True)
            
            # 优先使用样本数据服务
            if self.sample_data_service:
                logger.info(f"使用样本数据服务加载第{self.current_page}页数据")
                self._load_from_sample_service()
            elif self.data_loader:
                logger.info(f"使用数据加载器加载第{self.current_page}页数据")
                self._load_from_data_loader()
            else:
                logger.warning("没有可用的数据加载方式")
                self._current_data = []
                self.total_items = 0
                self.total_pages = 0
            
        except Exception as e:
            logger.error(f"加载当前页数据失败: {e}")
            self._current_data = []
            self.total_items = 0
            self.total_pages = 0
        finally:
            self._loading = False
            self._update_pagination_info(loading=False)
    
    def _load_from_sample_service(self):
        """从样本数据服务加载数据"""
        try:
            from ..core.sample_data_service import PageRequest, SortOrder as ServiceSortOrder
            
            # 创建分页请求
            request = PageRequest(
                page=self.current_page,
                page_size=self.page_size,
                sort_field=self.sort_field,
                sort_order=ServiceSortOrder.DESC if self.sort_order == SortOrder.DESC else ServiceSortOrder.ASC,
                filters=self.filters
            )
            
            # 执行分页查询
            response = self.sample_data_service.get_samples_paginated(request)
            
            if response.success:
                # 更新数据
                self._current_data = response.samples
                self.total_items = response.total_items
                self.total_pages = response.total_pages
                
                logger.info(f"样本数据服务加载成功: 第{self.current_page}页，共{len(self._current_data)}条，总数{self.total_items}条")
            else:
                logger.error(f"样本数据服务加载失败: {response.message}")
                self._current_data = []
                self.total_items = 0
                self.total_pages = 0
                
        except Exception as e:
            logger.error(f"从样本数据服务加载数据失败: {e}")
            self._current_data = []
            self.total_items = 0
            self.total_pages = 0
    
    def _load_from_data_loader(self):
        """从数据加载器加载数据"""
        try:
            # 调用数据加载器获取分页数据
            result = self.data_loader(
                page=self.current_page,
                page_size=self.page_size,
                sort_field=self.sort_field,
                sort_order=self.sort_order.value,
                filters=self.filters
            )
            
            if result and isinstance(result, dict):
                self._current_data = result.get("samples", [])
                self.total_items = result.get("total_count", 0)
                self.total_pages = result.get("total_pages", 0)
                self.current_page = result.get("current_page", 1)
                
                logger.info(f"数据加载器加载成功: 第{self.current_page}页，共{len(self._current_data)}条记录")
            else:
                logger.warning("数据加载器返回无效结果")
                self._current_data = []
                self.total_items = 0
                self.total_pages = 0
                
        except Exception as e:
            logger.error(f"从数据加载器加载数据失败: {e}")
            self._current_data = []
            self.total_items = 0
            self.total_pages = 0
    
    def _update_pagination_info(self, loading: bool = False):
        """更新分页信息"""
        start_index = (self.current_page - 1) * self.page_size
        end_index = min(start_index + self.page_size, self.total_items)
        
        self._pagination_info = PaginationInfo(
            current_page=self.current_page,
            page_size=self.page_size,
            total_items=self.total_items,
            total_pages=self.total_pages,
            has_previous=self.current_page > 1,
            has_next=self.current_page < self.total_pages,
            start_index=start_index + 1 if self.total_items > 0 else 0,
            end_index=end_index,
            loading=loading
        )
    
    def get_current_data(self) -> List[Any]:
        """获取当前页数据"""
        if not self._current_data and not self._loading:
            self._load_current_page()
        return self._current_data
    
    def get_pagination_info(self) -> PaginationInfo:
        """获取分页信息"""
        return self._pagination_info
    
    def go_to_page(self, page: int) -> bool:
        """跳转到指定页"""
        if 1 <= page <= self.total_pages and page != self.current_page:
            self.current_page = page
            self._load_current_page()
            return True
        elif page == 1 and self.total_pages == 0:
            # 如果是第一页且总页数为0，尝试加载数据
            self.current_page = 1
            self._load_current_page()
            return True
        return False
    
    def next_page(self) -> bool:
        """下一页"""
        return self.go_to_page(self.current_page + 1)
    
    def previous_page(self) -> bool:
        """上一页"""
        return self.go_to_page(self.current_page - 1)
    
    def first_page(self) -> bool:
        """第一页"""
        return self.go_to_page(1)
    
    def last_page(self) -> bool:
        """最后一页"""
        return self.go_to_page(self.total_pages)
    
    def get_page_info_text(self) -> str:
        """获取分页信息文本"""
        if self.total_items == 0:
            return "暂无数据"
        
        start_index = (self.current_page - 1) * self.page_size + 1
        end_index = min(start_index + self.page_size - 1, self.total_items)
        
        return f"第 {start_index}-{end_index} 条，共 {self.total_items} 条，第 {self.current_page}/{self.total_pages} 页"
    
    def is_loading(self) -> bool:
        """是否正在加载"""
        return self._loading
    
    def has_data(self) -> bool:
        """是否有数据"""
        return len(self._current_data) > 0
    
    def get_current_page_size(self) -> int:
        """获取当前页实际数据条数"""
        return len(self._current_data)
    
    def clear_cache(self):
        """清除缓存数据"""
        self._current_data = []
        self._loading = False
        logger.info("分页缓存已清除")
    
    def refresh_current_page(self):
        """刷新当前页数据"""
        logger.info(f"刷新第{self.current_page}页数据")
        self._load_current_page()
    
    def search_samples(self, search_text: str) -> bool:
        """
        搜索样本数据
        
        Args:
            search_text: 搜索文本
            
        Returns:
            bool: 搜索是否成功
        """
        try:
            if not self.sample_data_service:
                logger.warning("样本数据服务未设置，无法执行搜索")
                return False
            
            from ..core.sample_data_service import PageRequest, SortOrder as ServiceSortOrder
            
            # 创建搜索请求
            request = PageRequest(
                page=1,  # 搜索时重置到第一页
                page_size=self.page_size,
                sort_field=self.sort_field,
                sort_order=ServiceSortOrder.DESC if self.sort_order == SortOrder.DESC else ServiceSortOrder.ASC,
                filters=self.filters
            )
            
            # 执行搜索
            response = self.sample_data_service.search_samples(search_text, request)
            
            if response.success:
                # 更新数据
                self.current_page = 1
                self._current_data = response.samples
                self.total_items = response.total_items
                self.total_pages = response.total_pages
                
                logger.info(f"搜索成功: 找到{self.total_items}条记录")
                return True
            else:
                logger.error(f"搜索失败: {response.message}")
                return False
                
        except Exception as e:
            logger.error(f"搜索样本数据失败: {e}")
            return False
    
    def advanced_search(self, conditions: Dict[str, Any]) -> bool:
        """
        高级搜索样本数据
        
        Args:
            conditions: 高级搜索条件
            
        Returns:
            bool: 搜索是否成功
        """
        try:
            if not self.sample_data_service:
                logger.warning("样本数据服务未设置，无法执行高级搜索")
                return False
            
            from ..core.sample_data_service import PageRequest, SortOrder as ServiceSortOrder
            
            # 创建高级搜索请求
            request = PageRequest(
                page=1,  # 搜索时重置到第一页
                page_size=self.page_size,
                sort_field=self.sort_field,
                sort_order=ServiceSortOrder.DESC if self.sort_order == SortOrder.DESC else ServiceSortOrder.ASC,
                filters=self.filters
            )
            
            # 执行高级搜索
            response = self.sample_data_service.get_advanced_search_results(conditions, request)
            
            if response.success:
                # 更新数据
                self.current_page = 1
                self._current_data = response.samples
                self.total_items = response.total_items
                self.total_pages = response.total_pages
                
                logger.info(f"高级搜索成功: 找到{self.total_items}条记录")
                return True
            else:
                logger.error(f"高级搜索失败: {response.message}")
                return False
                
        except Exception as e:
            logger.error(f"高级搜索样本数据失败: {e}")
            return False

class LazyDataLoader:
    """懒加载数据管理器"""
    
    def __init__(self, db_manager, cache_size: int = 50):
        """
        初始化懒加载数据管理器
        
        Args:
            db_manager: 数据库管理器
            cache_size: 缓存大小
        """
        self.db_manager = db_manager
        self.cache_size = cache_size
        self._cache = {}  # 页面缓存
        self._access_order = []  # 访问顺序
        
        logger.info(f"懒加载数据管理器初始化完成，缓存大小: {cache_size}")
    
    def load_page(self, page: int, page_size: int, sort_field: str = "updated_at", 
                  sort_order: str = "DESC", filters: Dict[str, Any] = None) -> Dict[str, Any]:
        """
        加载指定页数据
        
        Args:
            page: 页码
            page_size: 每页大小
            sort_field: 排序字段
            sort_order: 排序方式
            filters: 过滤条件
            
        Returns:
            Dict: 包含分页信息和数据的字典
        """
        try:
            # 生成缓存键
            cache_key = self._generate_cache_key(page, page_size, sort_field, sort_order, filters)
            
            # 检查缓存
            if cache_key in self._cache:
                logger.debug(f"从缓存获取第{page}页数据")
                self._update_access_order(cache_key)
                return self._cache[cache_key]
            
            # 从数据库加载数据
            logger.info(f"从数据库加载第{page}页数据")
            result = self._load_from_database(page, page_size, sort_field, sort_order, filters)
            
            # 缓存结果
            self._cache_result(cache_key, result)
            
            return result
            
        except Exception as e:
            logger.error(f"加载第{page}页数据失败: {e}")
            return {
                "samples": [],
                "total_count": 0,
                "total_pages": 0,
                "current_page": page
            }
    
    def _generate_cache_key(self, page: int, page_size: int, sort_field: str, 
                           sort_order: str, filters: Dict[str, Any]) -> str:
        """生成缓存键"""
        filter_str = str(sorted(filters.items())) if filters else "{}"
        return f"{page}_{page_size}_{sort_field}_{sort_order}_{filter_str}"
    
    def _load_from_database(self, page: int, page_size: int, sort_field: str, 
                           sort_order: str, filters: Dict[str, Any]) -> Dict[str, Any]:
        """从数据库加载数据"""
        try:
            # 使用数据库管理器的分页查询方法
            result = self.db_manager.get_samples_paginated(
                page=page, 
                page_size=page_size,
                sort_field=sort_field,
                sort_order=sort_order,
                filters=filters
            )
            
            return result
            
        except Exception as e:
            logger.error(f"从数据库加载数据失败: {e}")
            return {
                "samples": [],
                "total_count": 0,
                "total_pages": 0,
                "current_page": page
            }
    
    def _cache_result(self, cache_key: str, result: Dict[str, Any]):
        """缓存结果"""
        try:
            # 如果缓存已满，移除最久未访问的项
            if len(self._cache) >= self.cache_size:
                self._remove_oldest_cache()
            
            # 添加新缓存
            self._cache[cache_key] = result
            self._access_order.append(cache_key)
            
            logger.debug(f"数据已缓存，当前缓存大小: {len(self._cache)}")
            
        except Exception as e:
            logger.error(f"缓存结果失败: {e}")
    
    def _update_access_order(self, cache_key: str):
        """更新访问顺序"""
        try:
            if cache_key in self._access_order:
                self._access_order.remove(cache_key)
            self._access_order.append(cache_key)
        except Exception as e:
            logger.error(f"更新访问顺序失败: {e}")
    
    def _remove_oldest_cache(self):
        """移除最久未访问的缓存"""
        try:
            if self._access_order:
                oldest_key = self._access_order.pop(0)
                if oldest_key in self._cache:
                    del self._cache[oldest_key]
                    logger.debug(f"已移除最久未访问的缓存: {oldest_key}")
        except Exception as e:
            logger.error(f"移除最久未访问的缓存失败: {e}")
    
    def clear_cache(self):
        """清除所有缓存"""
        try:
            self._cache.clear()
            self._access_order.clear()
            logger.info("所有缓存已清除")
        except Exception as e:
            logger.error(f"清除缓存失败: {e}")
    
    def get_cache_info(self) -> Dict[str, Any]:
        """获取缓存信息"""
        return {
            "cache_size": len(self._cache),
            "max_cache_size": self.cache_size,
            "cached_pages": list(self._cache.keys())
        }
